package com.struc.td;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;

public class EnemyNormal extends Enemy{
	// Colors
	private static float BLACK = Color.BLACK.toFloatBits();
	private static float RED = Color.RED.toFloatBits();
	//stats
	private int hitpoints;
	private int maxHitPoints;
	private float basespeed = 1f;
	private float currentspeed;
	private float speedregen = 0.01f;
	private float armor = 0.8f;
	private int level;
	private boolean reachedGoal;
	// Sprites / Textures
	private Texture unit;
	private Sprite sprite;
	private Sprite sprite1;
	private Sprite sprite2;
	private Sprite sprite3;
	private Sprite sprite4;
	private Array<Sprite> spritelist;
	private int renderorder = 0;
	private BitmapFont font;
	private Sprite infoBackground;
	private Sprite exitInfo;
	private Texture pixel;
	//pos
	private float xPos;
	private float yPos;
	private Array<Waypoint> waypoints;
	private int currentWaypoint;
	//timers
	private int timer;
	private int animationTimer;
	
	/*Creates a new normal enemy given the level of the enemy, the order
	 *of the enemy in the enemy wave and a reference to the waypoints of 
	 *the map.
	 */
	public EnemyNormal(int level, int i, Array<Waypoint> waypoints2){
		reachedGoal = false;
		font = StaticTextures.font;
		currentWaypoint = 0;
		pixel = StaticTextures.pixel;
		spritelist = new Array<Sprite>();
		this.level = level;
		hitpoints = level*10;
		maxHitPoints = level*10;
		currentspeed= basespeed;
		waypoints= waypoints2;
		xPos = waypoints2.get(currentWaypoint).getX();
		yPos = -60*(i+2);
		unit = StaticTextures.entity_map;
		exitInfo = new Sprite(StaticTextures.info_panel_exitInfo,0,0,64,27);
		infoBackground = new Sprite(StaticTextures.enemy_normal_infoBG);
		sprite1 = new Sprite(unit,0,199,64,64);
		sprite = new Sprite(unit,64,199,64,64);
		sprite2 = new Sprite(unit,128,199,64,64);
		sprite3 = new Sprite(unit,192,199,64,64);
		sprite4 = new Sprite(unit,256,199,64,64);
		sprite.setPosition(xPos,yPos);
		sprite1.setPosition(xPos,yPos);
		sprite2.setPosition(xPos,yPos);
		sprite3.setPosition(xPos,yPos);
		sprite4.setPosition(xPos,yPos);
		spritelist.add(sprite);
		spritelist.add(sprite4);
		spritelist.add(sprite1);
		spritelist.add(sprite4);
		spritelist.add(sprite);
		spritelist.add(sprite3);
		spritelist.add(sprite2);
		spritelist.add(sprite3);

		Vector2 rotCalc = new Vector2();
		rotCalc.x = waypoints.get(currentWaypoint).getX()-xPos;
		rotCalc.y = waypoints.get(currentWaypoint).getY()-yPos;
		sprite.setRotation(rotCalc.angle());
		sprite1.setRotation(rotCalc.angle());
		sprite2.setRotation(rotCalc.angle());
		sprite3.setRotation(rotCalc.angle());
		sprite4.setRotation(rotCalc.angle());
	}

	/* Updates the timers. animationTimer takes care of what
	 * sprite to render. timer takes care of movement.
	 */
	public void update() {
		animationTimer += Gdx.graphics.getDeltaTime()*1000;
		timer += Gdx.graphics.getDeltaTime()*1000;
		if (animationTimer > 200) {
			animationTimer-=200;
			renderorder+=1;
			renderorder = renderorder % spritelist.size;
		}
		if(timer > 100){
			timer -= 100;
			Waypoint w = waypoints.get(currentWaypoint);
			Vector2 vec = new Vector2();
			vec.x = w.getX()-xPos;
			vec.y = w.getY()-yPos;
			float totDistance = (float) Math.sqrt(Math.pow(Math.abs(vec.x) + Math.abs(vec.y),2));
			vec.x = vec.x/totDistance;
			vec.y = vec.y/totDistance;  
			xPos += vec.x * (8* currentspeed);
			yPos += vec.y * (8* currentspeed);
			sprite.setPosition(xPos,yPos);
			sprite1.setPosition(xPos,yPos);
			sprite2.setPosition(xPos,yPos);
			sprite3.setPosition(xPos,yPos);
			sprite4.setPosition(xPos,yPos);
			if(totDistance < 5) {
				if (currentWaypoint == waypoints.size-1) {
					reachedGoal = true;
				} else {
					currentWaypoint++;
					Vector2 rotCalc = new Vector2();
					rotCalc.x = waypoints.get(currentWaypoint).getX()-xPos;
					rotCalc.y = waypoints.get(currentWaypoint).getY()-yPos;
					sprite.setRotation(rotCalc.angle());
					sprite1.setRotation(rotCalc.angle());
					sprite2.setRotation(rotCalc.angle());
					sprite3.setRotation(rotCalc.angle());
					sprite4.setRotation(rotCalc.angle());
				}

			}

			if(currentspeed < basespeed){
				currentspeed+= speedregen;
			}
		}
	}

	//renders the enemy
	public void render(SpriteBatch sb) {
		spritelist.get(renderorder).draw(sb);
	}

	//check if dead
	public boolean getDead() {
		if (hitpoints <= 0){
			return true;}
		return false;
	}

	/* Takes a projectile as parameter and runs the 
	 * apropriate code.
	 */
	public void gotHit(Projectile t) {
		if (t instanceof ProjectileDamage ){
			hitpoints -= ((ProjectileDamage) t).getDmg()*armor;
			if (hitpoints < 0) {
				hitpoints = 0;
			}
		} else if (t instanceof ProjectileSlow ){  
			if(currentspeed > ((ProjectileSlow) t).getSlow()){
				currentspeed =((ProjectileSlow) t).getSlow();
			}
		}
	}
	//a method to calculate the bounty of the enemy
	public int getValue() {
		return ((2^(level+3))+1);
	}
	
	//renders the infopanel
	public void renderInfo(SpriteBatch sb) {
		infoBackground.setBounds(Gdx.graphics.getWidth()-Gdx.graphics.getWidth()/3, 0, Gdx.graphics.getWidth()/3, Gdx.graphics.getHeight());
		exitInfo.setBounds(infoBackground.getX(), Gdx.graphics.getHeight()-Gdx.graphics.getHeight()/15, infoBackground.getWidth()/3, infoBackground.getHeight()/15);
		infoBackground.draw(sb,0.8f);
		exitInfo.draw(sb, 0.6f);

		font.draw(sb, "Enemy Hitpoints: " + hitpoints,(Gdx.graphics.getWidth()) - (infoBackground.getWidth() ) , 400);
		font.draw(sb, "Enemy Armor: " + armor*100 + "%",(Gdx.graphics.getWidth()) - (infoBackground.getWidth() ) , 380);
		font.draw(sb, "Enemy Type: " + "Normal",(Gdx.graphics.getWidth()) - (infoBackground.getWidth() ) , 360);
		font.draw(sb, "Enemy Speed: " + currentspeed*100 + "%",(Gdx.graphics.getWidth()) - (infoBackground.getWidth() ) , 340);
	}

	public Rectangle getBounds() {
		return spritelist.get(renderorder).getBoundingRectangle();
	}

	public Rectangle getInfoBounds() {
		return infoBackground.getBoundingRectangle();
	}

	public Rectangle getExitInfoRect() {
		return exitInfo.getBoundingRectangle();
	}
	
	//renders the enemy health bar
	public void renderHp(SpriteBatch sb) {
		sb.setColor(BLACK);
		sb.draw(pixel,xPos,yPos+60,40,4);
		sb.setColor(RED);
		sb.draw(pixel,xPos,yPos+60,(float) hitpoints/maxHitPoints*40,4);
	}
	public boolean reachedGoal() {
		return reachedGoal;
	}
	
	// Test methods
	public void setTimer(int t) {
		timer = t;
		animationTimer = t;
	}
	public float currentSpeed() {
		return currentspeed;
	}
}